home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / c_windw / dbfdict.c < prev    next >
Text File  |  1987-12-28  |  12KB  |  332 lines

  1. /*    (c) Marietta Systems, Inc 1987
  2. *    All rights reserved */
  3. /*    
  4. *    This program sets up the dictionary for a dBase3+ file
  5. *
  6. *    The maximum number of fields is 20, and memo fields are not supported
  7. */
  8. #include "mtest.h"
  9. int  dbf_cr(char*);
  10. int  dbf_init(int*, struct DBF_DEF*, char*, int);
  11. int  dbf_name(byte*);
  12. void linedisp(struct DBF_DEF*, int);
  13. int  lineacpt(struct DBF_DEF*, int);
  14. void lineshuf(struct DBF_DEF*, int, int);
  15. #define point "\075\020"
  16. /*
  17. *
  18. *        Function to create dbase3+ file & setup data dictionary 
  19. *
  20. */
  21. int dbf_cr(name)
  22. char *name;{
  23.     struct DBF_DEF format[20];
  24.     int fields = 0, fld = 0, fh = fileopen(name, dbase3, recreate), z, ret;
  25.     byte kk = 0;
  26.     if (fh < 0) return fh;
  27.   /* setup */
  28.     for (z = 0; z < 20; format[z++].dbf_type = 'C')
  29.         format[z].dbf_name[0] = format[z].dbf_len = format[z].dbf_dec = 0;
  30.   /* setup function key map */
  31.     KEYMATCH[0] = 0X430; /* Up & right arrow, Ctrl+Enter */
  32.     KEYMATCH[1] = 0X108; /* Down & left arrow */
  33.     KEYMATCH[2] = KEYMATCH[3] = KEYMATCH[6] = KEYMATCH[7] = 0;
  34.     KEYMATCH[4] = 0X3000; /* F5, F6 */
  35.     disp_err("",1); /* force display of new function keys */
  36.     if (1 > mk_wndw(TOP_LINE + 1, 1, SCRN_LEN - 1, 80,
  37.         "Enter data dictionary details for dBase3+ file")) goodbye(13);
  38.     kk = INSERT; /* must first insert into an empty dictionary */
  39.     linedisp(format, 0);
  40.   /* main accept loop */
  41.     for(;;){
  42.         if (!kk) linedisp(format, fld);
  43.         display(point, fld+1, 5, blink);
  44.         set_crsr(fld+1, 1);
  45.         if (!kk) kk = grabchar();
  46.         display(": ", fld+1, 5, high);
  47.         switch((int)kk){
  48.             case CRS_UP: if (fld) fld--; kk = 0; break;
  49.             case CRS_DN: if (fld < 20 && fld < fields) fld++; 
  50.                 kk = 0; break;
  51.             case CRS_RT: case ENTER: case TAB: 
  52.                 if (fld == fields) {kk = INSERT; break;}
  53.                 if ((ret = lineacpt(format, fld)) < 0) goodbye(11);
  54.                 kk = (ret ? INCHAR : 0); 
  55.                 if (format[fld].dbf_name[0] == 0 && fields != fld)
  56.                     {lineshuf(format, fld, 1); fields--;}
  57.                 break;
  58.             case QUIT: kk = 0; break;
  59.             case INSERT: if (fields >= 20) 
  60.                     {disp_err("No more fields allowed",1); break;}
  61.                 if (fld < fields) lineshuf(format, fld, -1);
  62.                 if ((ret = lineacpt(format, fld)) < 0) goodbye(11);
  63.                 kk = (ret ? INCHAR : 0); 
  64.                 if (format[fld].dbf_name[0] == 0)
  65.                     lineshuf(format, fld, 1); 
  66.                     else {fld++; fields++;}
  67.                 if (!kk && fld >= fields - 1) kk = INSERT;
  68.             break;
  69.             case DELETE:if (fields && fld < fields) 
  70.                     {lineshuf(format, fld, 1); fields--;}
  71.                 kk = 0; break;
  72.             case HELP: if (mk_wndw(3,48,13,80,"Dictionary help") > 1){
  73.                     display("To change a line, move the    ",1,1,high);
  74.                     display("  cursor with the up and down ",2,1,high);
  75.                     display("  keys, then make your selec- ",3,1,high);
  76.                     display("  tion with the Enter key.    ",4,1,high);
  77.                     display("To insert a line press F5 key ",5,1,high);
  78.                     display("To delete a line press F6 key ",6,1,high);
  79.                     display("To exit, press the F10 key    ",7,1,high);
  80.                     display("<< Press ESC key to continue>>",9,1,low);
  81.                     while(grabchar() != ESC) 
  82.                         disp_err("Press ESC key", 2);
  83.                     rm_wndw();
  84.                     }
  85.                 kk = 0; break; 
  86.             default: warble(1000); idleloop(ERR_BEEP); warble(0); 
  87.                 kk = 0; break;
  88.             } /* end switch */
  89.         if (INCHAR == QUIT && disp_qry("Have you completed entry")) 
  90.             break;
  91.         } /* end for loop */
  92.     ret =  ((fields && disp_qry("Write the dictionary to file")) ?
  93.         dbf_init(&fh, format, name, fields) : -1);
  94.     fileclos(fh); rm_wndw(); return ret;
  95.     }  /* end function dbf_cr */
  96. /*
  97. *
  98. *        Function to write dictionary to new dbase3+ file
  99. *
  100. */
  101. int dbf_init(fh, format, name, fields)
  102. int *fh, fields;
  103. struct DBF_DEF *format; 
  104. char *name;{
  105.     int z;
  106.     short *sptr;
  107.     long rec_nbr = 0L;
  108.     fileinit(*fh, 0, 32, 0L); /* nil start, 32 byte record file */
  109.     memset(FN[*fh].record, 0, 32);
  110.   /* write the system header 32 byte record */
  111.     FN[*fh].record[0] = SYS_REC;
  112.     sptr = (short *) &FN[*fh].record[8];
  113.     sptr[0] = fields * 32    + 33; /* start of data */
  114.     for (sptr[1] = 1, z = 0 ; z < fields ; z++) 
  115.         {sptr[1] += format[z].dbf_len;} /* data record length */
  116.     if (filewrit(*fh, &rec_nbr) < 0) goto error;
  117.   /* write the field dictionary records */
  118.     for (z = 0 ; z < fields ; z++){
  119.         memset(FN[*fh].record, 0, 32);
  120.         memcpy(FN[*fh].record, format[z].dbf_name, 11);
  121.         FN[*fh].record[11] = format[z].dbf_type;
  122.         FN[*fh].record[16] = format[z].dbf_len;
  123.         FN[*fh].record[17] = format[z].dbf_dec;
  124.         if (filewrit(*fh, &rec_nbr) < 0) goto error;
  125.         }
  126.   /* write the dBase3+ header terminator */
  127.       FN[*fh].rec_len = 1; /* hairy but necessary technique here */
  128.       FN[*fh].record[0] = 0X0D;        
  129.       if (filewrit(*fh, &rec_nbr) < 0) goto error;
  130.     FN[*fh].rec_len = 32; 
  131.     FN[*fh].prime = 0L; /* set file record count back to zero */
  132.     return 0;
  133.     error: fileclos(*fh); 
  134.     disp_msg("Terminate?? in dbf_init ",(int)rec_nbr + 100); read_kb();
  135.     *fh = fileopen(name, dbase3, recreate);
  136.     return -1;
  137.     } /* end function dbf_init */
  138. /*
  139. *
  140. *        Function to display line of data dictionary
  141. *
  142. */
  143. void linedisp(format, line)
  144. struct DBF_DEF *format;
  145. int line; {
  146.     byte text[12];
  147.     display("Name: ", line + 1, 1, high);
  148.     justify(left, text, format[line].dbf_name, 10, 0);
  149.     display(text, 0, 0, ACC_DISP); 
  150.     display("  Type: ", 0, 0, high);
  151.     switch((int)format[line].dbf_type){
  152.         case 0:
  153.         case 32: 
  154.         case 'C':display("Character", 0, 0, ACC_DISP); break;
  155.         case 'D':display("Date     ", 0, 0, ACC_DISP); break;
  156.         case 'L':display("Logical  ", 0, 0, ACC_DISP); break;
  157.         case 'M':display("Memo     ", 0, 0, ACC_DISP); break;
  158.         case 'N':display("Numeric  ", 0, 0, ACC_DISP); break;
  159.         default: display("?????????", 0, 0, ACC_DISP); break;
  160.         }
  161.     display("  Size: ", 0, 0, high);
  162.     if (format[line].dbf_type == 'N') 
  163.         sprintf(text,"%3u %u",format[line].dbf_len, format[line].dbf_dec);
  164.         else sprintf(text, "%3u  ", format[line].dbf_len); 
  165.     display(text, 0, 0, ACC_DISP); display(" ", line+1, 45, low);
  166.     }  /* end function linedisp */
  167. /*
  168. *
  169. *        Function to validate a dbase3+ field name
  170. *
  171. */
  172. int dbf_name (name)
  173. byte *name;{
  174.     int z, len;
  175.     concat(name, 0); /* strip trailing spaces */
  176.     strupr(name);    /* turn alpha characters into uppercase */
  177.     len = strlen(name);
  178.     if (len > 10 || !len || !isalpha(name[0])) goto error;
  179.     for (z = 1 ; z < len ; z++) 
  180.         if (!isalpha(name[z]) && !isdigit(name[z]) && name[z] != '_')
  181.             goto error;
  182.     return 1;
  183.     error: disp_err("Invalid character in fieldname",3);
  184.     return 0;
  185.     }
  186. /*
  187. *
  188. *        Function to accept a new line in dictionary
  189. *
  190. */
  191. #define CR_MSG0 "                               "
  192. #define CR_MSG1 " Char, Date, Logical, Numeric  "
  193. #define CR_MSG2 " Maximum of 254 bytes in size  "
  194. #define CR_MSG3 " Maximum of 32 bytes in Numeric"
  195. #define CR_MSG4 " Maximum of 8 decimal places   "
  196. #define CR_MSG5 " Only A - Z, 0 - 9, and _      "
  197. int lineacpt(format, fld)
  198. struct DBF_DEF *format;
  199. int fld;{
  200.     int ret, ans, z;
  201.     char text[12];
  202.   /*    */
  203.     name: display(CR_MSG5, fld+1, 48, low);
  204.       set_crsr(fld+1, 7);
  205.     ret = accept(format[fld].dbf_name, left, alt_reverse, 10, 0);
  206.       if (ret && INCHAR != CRS_RT) goto end;
  207.     if (!dbf_name(format[fld].dbf_name)) goto name;
  208.     display(format[fld].dbf_name, fld+1, 7, ACC_DISP);
  209.     for (z = 0 ; z < 20 ; z++) 
  210.         if (z != fld && !strcmp((byte*)format[fld].dbf_name, 
  211.             (byte*)format[z].dbf_name))
  212.             {disp_err("Duplicate name",3); goto name;}
  213.   /*    */
  214.     type: display(CR_MSG1, fld+1, 48, low);
  215.       set_crsr(fld+1, 25);
  216.     text[0] = format[fld].dbf_type; text[1] = 0;
  217.     ret = accept(text, left, alt_reverse, 1, 0);
  218.     if (ret) if (INCHAR == CTL_ENT || INCHAR == CRS_LT) goto name; 
  219.         else if (INCHAR != CRS_RT) goto end;
  220.     format[fld].dbf_type = text[0] = toupper(text[0]);
  221.    /*    */
  222.     switch ((int)text[0]){
  223.         case 'C': display("Character", fld+1, 25, ACC_DISP);
  224.             sprintf(text, "%3u", format[fld].dbf_len);
  225.             c_size: display(CR_MSG2, fld+1, 48, low);
  226.               set_crsr(fld+1, 42);
  227.             ret = accept(text, code, alt_low, 3, 0);
  228.             if (ret) if (INCHAR == CTL_ENT || INCHAR == CRS_LT) 
  229.             goto type; 
  230.                 else break;
  231.             if ((ans = atoi(text)) > 254 || !ans) 
  232.                 {disp_err("size must be 1 thru 254", 1); goto c_size;}
  233.             format[fld].dbf_len = ans;
  234.             break;
  235.         case 'D': break;
  236.         case 'L': break;
  237.         case 'N': display("Numeric  ", fld+1, 25, ACC_DISP);
  238.             n1_size: sprintf(text, "%3u", format[fld].dbf_len);
  239.             display(CR_MSG3, fld+1, 48, low);
  240.               set_crsr(fld+1, 42);
  241.             ret = accept(text, code, alt_low, 3, 0);
  242.             if (ret) if (INCHAR == CTL_ENT || INCHAR == CRS_LT) 
  243.             goto type; 
  244.                 else if (INCHAR != CRS_RT) break;
  245.             if ((ans = atoi(text)) > 32 || !ans) 
  246.                 {disp_err("size must be 1 thru 32", 1); goto n1_size;}
  247.             format[fld].dbf_len = ans;
  248.             n2_size: sprintf(text, "%1u", format[fld].dbf_dec);
  249.             display(CR_MSG4, fld+1, 48, low);
  250.               set_crsr(fld+1, 46);
  251.             ret = accept(text, code, alt_low, 1, 0);
  252.             if (ret) if (INCHAR == CTL_ENT || INCHAR == CRS_LT) 
  253.             goto n1_size; 
  254.                 else break;
  255.             if ((ans = atoi(text)) > 8) 
  256.                 {disp_err("Maximum of 8 decimal places", 1); 
  257.                 goto n2_size;}
  258.             format[fld].dbf_dec = ans;
  259.             break;
  260.          default: disp_err("Invalid type selection", 1); goto type;
  261.          } /* end switch */
  262.   /*  exit validation */
  263.     end: if (!format[fld].dbf_name[0]) return ret; /* empty */
  264.     switch((int)format[fld].dbf_type){
  265.         case 'C': format[fld].dbf_dec = 0;
  266.             if (format[fld].dbf_len == 255) goto c_size;
  267.             break;
  268.         case 'D': format[fld].dbf_len = 8; 
  269.             format[fld].dbf_dec = 0; break;
  270.         case 'L': format[fld].dbf_len = 1;
  271.             format[fld].dbf_dec = 0; break;
  272.         case 'N': if (format[fld].dbf_len > 32) goto n1_size;
  273.             if (format[fld].dbf_dec > 8) goto n2_size;
  274.             if (format[fld].dbf_dec + 2 > format[fld].dbf_len) 
  275.                     goto n1_size;
  276.             break;
  277.         default: goto type;
  278.         } /* end switch */
  279.     display(CR_MSG0, fld+1, 48, low); /* blank out help area */
  280.     if (!format[fld].dbf_len) memset(format[fld].dbf_name, 0, 11);
  281.     linedisp(format, fld);
  282.     return ret;
  283.     }    /* end function lineacpt */
  284. /*
  285. *
  286. *        Function to shuffle up and down the dictionary display
  287. *
  288. */
  289. void lineshuf(format, fld, up)
  290. struct DBF_DEF *format;
  291. int fld, up;{
  292.     int to, from, base;
  293.     up = (up < 0 ? -1 : 1);
  294.     scroll(up, fld); /* scroll window up or down */
  295.     to = (up > 0 ? fld : 19);
  296.     from = (up > 0 ? fld + 1 : 18);
  297.     base = (up > 0 ? 19 : fld);
  298.     for (; base != to ; to += up, from += up){
  299.         memcpy(format[to].dbf_name, format[from].dbf_name, 11);
  300.         format[to].dbf_type = format[from].dbf_type;
  301.         format[to].dbf_len = format[from].dbf_len;
  302.         format[to].dbf_dec = format[from].dbf_dec;
  303.         }
  304.     memset(format[to].dbf_name, 0, 11);
  305.     format[to].dbf_type = 'C';
  306.     format[to].dbf_len = 0;
  307.     format[to].dbf_dec = 0;
  308.     if (up < 0) linedisp(format, fld);
  309.     }     /* end function lineshuf */
  310. /*
  311. *
  312. *    Main section
  313. *
  314. */
  315. void main(){
  316. char name[51];
  317. int z, fh;
  318. clr_scrn("dBase3+ dictionary create");
  319. strcpy(name, "dbftest.dbf");
  320. for (;;){
  321.     for (z = 0 ; z < 8 ; KEYMATCH[z++] = 0); disp_err("",1);
  322.     display("Enter file name  ", 20, 2, low);
  323.     if (accept(name, left, alt_reverse, 50, 0)) goodbye(0);
  324.     if ((fh = fileopen(name, dbase3, readonly)) < 0) continue;
  325.     if (fh && FN[fh].fnext != NULL 
  326.         && !disp_qry("Do you wish to overwrite file")) 
  327.         {fileclos(fh); continue;}
  328.         else if (fh) {fileclos(fh); if (fileback(name) < 1) continue;}
  329.     if (!dbf_cr(name)) {name[0] = 0; disp_err("Dictionary created", 1);}
  330.         else disp_err("Error end to dict create", 2);   
  331.     }
  332. }